package com.erdos.core.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.erdos.common.pagination.Page;
import com.erdos.common.service.BaseCRUDService;
import com.erdos.common.web.LoginUtil;
import com.erdos.core.constant.ReferenceConstant;
import com.erdos.core.dao.AttributeDao;
import com.erdos.core.dao.AttributeValueDao;
import com.erdos.core.entity.Attribute;
import com.erdos.core.entity.AttributeValue;
import com.erdos.core.entity.AttributeValueVO;
import com.erdos.core.entity.FieldVO;
import com.erdos.core.exception.ReferenceTableConfigException;
import com.erdos.core.service.AttributeValueService;
import com.erdos.core.service.ReferenceService;

public class AttributeValueServiceImpl extends BaseCRUDService<AttributeValue>
        implements AttributeValueService {

    private static final long serialVersionUID = -7233167794938611690L;

    private static final Log logger = LogFactory
            .getLog(AttributeValueServiceImpl.class);
    private AttributeDao attributeDao;
    private AttributeValueDao attributeValueDao;
    private ReferenceService referenceService;

    /**
     * 传入一个object代码和工厂代码facilityId ，返回对应的属性值集合
     * 主要用于对象创建的场景
     * @param object
     * @param facilityId
     * @return
     * @author xiali2
     * @since  2008-7-23
     */
    public List<AttributeValueVO> findAttributeValues(String object,
            String facilityId, Locale locale) {
        Page<AttributeValueVO> p = this.findAttributesByPage(object,
                facilityId, locale, new HashMap<String, Object>(), 1,
                Integer.MAX_VALUE);
        return p.getResultList();
    }

    public List<AttributeValueVO> findAttributeValues(String object,
            String facilityId, Locale locale, Map<String, Object> attParams) {
        Page<AttributeValueVO> p = this.findAttributesByPage(object,
                facilityId, locale, attParams, 1, Integer.MAX_VALUE);
        return p.getResultList();
    }

    /**
     * 根据object代码、工厂代码facilityId 、instanceSid对象主键，查询对应的属性值集合
     * 主要用于对象编辑的场景
     * @param object
     * @param facilitySid
     * @param instanceSid
     * @return
     * @author xiali2
     * @since  2008-7-21
     */
    public List<AttributeValueVO> findAttributeValues(String object,
            String facilityId, Long instanceSid, Locale locale) {
        Page<AttributeValueVO> p = this.findAttributeValues(object, facilityId,
                instanceSid, locale, new HashMap<String, Object>(), 1,
                Integer.MAX_VALUE);
        return p.getResultList();
    }

    /**
     * 传入组装好的AttributeValueVO集合，接口负责保存
     * @param attributeValues
     */
    public void saveAttributeValues(List<AttributeValueVO> attributeValues) {
        // 不同的对象操作集合
        List<AttributeValue> insertAttributeValues = new ArrayList<AttributeValue>();
        List<AttributeValue> updateAttributeValues = new ArrayList<AttributeValue>();
        // 获取所有object定义集合
        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        // 获取sequence表名对象映射集合
        Map<String, String> sequenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_TABLE_SEQUENCE_MAP);
        // 获取对应的表
        AttributeValueVO attributeValueVOTemp = (AttributeValueVO) attributeValues
                .get(0);
        String tableNameCode = attributeValueVOTemp.getObject();
        String tableName = referenceMap.get(tableNameCode);
        logger.debug("saveAttributeValues tableName=" + tableName);
        // 根据表名查找对应的Sequence对象的名字。
        String sequenceName = sequenceMap.get(tableName);

        // 得到关联已有Field对象集合
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("tableName", tableName);
        params.put("instanceSid", attributeValueVOTemp.getInstanceSid());
        List<AttributeValue> values = attributeValueDao.findByParams(params);
        Set<Long> existFieldSids = new HashSet<Long>();
        for (AttributeValue value : values) {
            existFieldSids.add(value.getFieldSid());
        }

        // 遍历传入集合对象，将对象改装成AttributeValue对象并根据具体SID的值分类
        for (AttributeValueVO attribateVO : attributeValues) {
            // 对现有的属性数据进行对象转换
            AttributeValue attributeValueTemp = new AttributeValue();
            attributeValueTemp.setAttributeValue(attribateVO
                    .getAttributeValue());
            attributeValueTemp.setFieldSid(attribateVO.getFieldSid());
            attributeValueTemp.setTableName(tableName);
            attributeValueTemp.setSequenceName(sequenceName);
            attributeValueTemp.setObject(attribateVO.getObject());
            attributeValueTemp.setVersion(attribateVO.getVersion());
            attributeValueTemp.setInstanceSid(attribateVO.getInstanceSid());
            attributeValueTemp.setCreatedBy(attribateVO.getCreatedBy());
            attributeValueTemp.setCreatedDt(attribateVO.getCreatedDt());
            attributeValueTemp.setUpdatedBy(attribateVO.getUpdatedBy());
            attributeValueTemp.setUpdatedDt(attribateVO.getUpdatedDt());
            attributeValueTemp.setLowerLimit(attribateVO.getLowerLimit());
            attributeValueTemp.setUpperLimit(attribateVO.getUpperLimit());
            attributeValueTemp.setRangeType(attribateVO.getRangeType());

            // 主键ID判断执行何种操作
            if (attribateVO.getSid() != null) {
                attributeValueTemp.setSid(attribateVO.getSid());
                updateAttributeValues.add(attributeValueTemp);
            } else {
                insertAttributeValues.add(attributeValueTemp);
            }
            logger.debug("attributeValueTemp=" + attributeValueTemp);
        }
        // 根据不同的集合类别调用不同的方法对数据进行持久化操作
        if (insertAttributeValues.size() > 0) {
            logger.debug("InsertAttributeValues...");
            attributeValueDao.insertAll(insertAttributeValues);
        }
        if (updateAttributeValues.size() > 0) {
            logger.debug("UpdateAttributeValues...");
            attributeValueDao.updateAll(updateAttributeValues);
        }
    }

    /**
     * 根据object代码、工厂代码facilityId 、instanceSid对象主键删除相关的value记录
     * 主要用于对象删除的场景
     * @param object
     * @param facilityId
     * @param instanceSid
     * @author xiali2
     * @since  2008-7-23
     */
    public void deleteAttributeValues(String object, String facilityId,
            Long instanceSid) {

        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        // 获取对应的表
        String valueTableName = referenceMap.get(object);
        Map<String, Object> params = new HashMap<String, Object>();
        // 封装参数对象
        params.put("valueTableName", valueTableName);
        params.put("object", object);
        params.put("instanceSid", instanceSid);
        // 根据条件删除信息
        attributeValueDao.deleteByParams(params);
    }

    /**
     * @return the attributeDao
     */
    public AttributeDao getAttributeDao() {
        return attributeDao;
    }

    /**
     * @param attributeDao the attributeDao to set
     */
    public void setAttributeDao(AttributeDao attributeDao) {
        this.attributeDao = attributeDao;
    }

    /**
     * @return the referenceService
     */
    public ReferenceService getReferenceService() {
        return referenceService;
    }

    /**
     * @param referenceService the referenceService to set
     */
    public void setReferenceService(ReferenceService referenceService) {
        this.referenceService = referenceService;
    }

    /**
     * @return the attributeValueDao
     */
    public AttributeValueDao getAttributeValueDao() {
        return attributeValueDao;
    }

    /**
     * @param attributeValueDao the attributeValueDao to set
     */
    public void setAttributeValueDao(AttributeValueDao attributeValueDao) {
        this.attributeValueDao = attributeValueDao;
    }

    /**
     * @author xiali2
     * @since  2008-8-12
     */
    public void insertHistory(String object, Long instanceSid,
            Map<String, Object> params) {

        // params.put("TRANSACTION_ID", "TRANSACTION_ID");
        // params.put("EVENT_ID", "EVENT_ID");

        // 获取所有object定义集合
        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        // 获取sequence表名对象映射集合
        Map<String, String> sequenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_TABLE_SEQUENCE_MAP);
        String tableName = referenceMap.get(object);
        if (StringUtils.isEmpty(tableName)) {
            throw new ReferenceTableConfigException("tableId:"
                    + ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP + ";key:"
                    + object);
        }

        String historyTableName = tableName + "_H";
        String historyTableSequence = sequenceMap.get(historyTableName);
        if (StringUtils.isEmpty(historyTableSequence)) {
            throw new ReferenceTableConfigException("tableId:"
                    + ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP + ";key:"
                    + historyTableName);
        }

        // 封装参数对象
        Map<String, Object> paramsTmp = new HashMap<String, Object>();
        paramsTmp.putAll(params);
        paramsTmp.put("valueTableName", tableName);
        paramsTmp.put("historyTableName", historyTableName);
        paramsTmp.put("historyTableSequence", historyTableSequence);

        paramsTmp.put("object", object);
        paramsTmp.put("instanceSid", instanceSid);

        paramsTmp.put("TRANSACTION_BY", LoginUtil.getUpcUserPin());

        attributeValueDao.insertHistory(paramsTmp);
    }

    /**
     * @author xiali2
     * @since  2008-8-12
     */
    public Long findMaxHistorySequence(String object, Long instanceSid) {
        // 获取所有object定义集合
        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        String tableName = referenceMap.get(object);
        if (StringUtils.isEmpty(tableName)) {
            throw new ReferenceTableConfigException("tableId:"
                    + ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP + ";key:"
                    + object);
        }

        String historyTableName = tableName + "_H";
        // 封装参数对象
        Map<String, Object> paramsTmp = new HashMap<String, Object>();
        paramsTmp.put("historyTableName", historyTableName);
        paramsTmp.put("object", object);
        paramsTmp.put("instanceSid", instanceSid);
        Long ret = (Long) attributeValueDao.findObjectBySqlID(
                "AttributeValue.findMaxHistorySequence", paramsTmp);
        if (ret == null) {
            return Long.valueOf(1);
        } else {
            return ret;
        }
    }

    /* (non-Javadoc)
     * @see com.hp.core.service.AttributeValueService#checkReftableConfigComlete(java.lang.String)
     */
    public boolean checkReftableConfigComlete(String object) {
        // 获取所有object定义集合
        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        String tableName = referenceMap.get(object);
        if (StringUtils.isEmpty(tableName)) {
            return false;
        } else {
            return true;
        }
    }

    /* (non-Javadoc)
     * @see com.hp.core.service.AttributeValueService#findAttributeValues(java.lang.String, java.lang.String, java.lang.Long, java.util.Locale, java.util.Map)
     */
    public List<AttributeValueVO> findAttributeValues(String object,
            String facilityId, Long instanceSid, Locale locale,
            Map<String, Object> attParams) {
        Page<AttributeValueVO> p = this.findAttributeValues(object, facilityId,
                instanceSid, locale, attParams, 1, Integer.MAX_VALUE);
        return p.getResultList();
    }

    /* (non-Javadoc)
     * @see com.hp.core.service.AttributeValueService#findAttributeValues(java.lang.String, java.lang.String, java.lang.Long, java.util.Locale, java.util.Map, int, int)
     */
    public Page<AttributeValueVO> findAttributeValues(String object,
            String facilityId, Long instanceSid, Locale locale,
            Map<String, Object> attParams, int pageNo, int limit) {
        Page<AttributeValueVO> attributeValueVOPage = this
                .findAttributesByPage(object, facilityId, locale, attParams,
                        pageNo, limit);
        if (attributeValueVOPage == null
                || attributeValueVOPage.getResultList() == null) {
            return attributeValueVOPage;
        }
        for (AttributeValueVO attrVO : attributeValueVOPage.getResultList()) {
            attrVO.setInstanceSid(instanceSid);
        }
        String tableName = this.getTableNameOfObject(object);

        Map<String, Object> params = new HashMap<String, Object>();
        // 组装查询参数
        if (instanceSid != null) {
            params.put("instanceSid", instanceSid);
        }
        params.put("object", object);
        // 设置查询的表名已取到可直接使用
        logger.debug("findAttributeValues tableName=" + tableName);
        params.put("tableName", tableName);
        List<AttributeValue> attributeValueList = attributeValueDao
                .findByParams(params);
        // 此处根据条件获取到的结果集合中有且只有一条或没有属性值记录
        if (attributeValueList != null && attributeValueList.size() > 0) {
            for (AttributeValueVO attributeValueVO : attributeValueVOPage
                    .getResultList()) {
                for (AttributeValue attributeValue : attributeValueList) {
                    if (attributeValue.getObject().equals(
                            attributeValueVO.getObject())
                            && attributeValue.getFieldSid().equals(
                                    attributeValueVO.getFieldSid())) {
                        attributeValueVO.setAttributeValue(attributeValue
                                .getAttributeValue());
                        attributeValueVO.setInstanceSid(attributeValue
                                .getInstanceSid());
                        attributeValueVO.setSid(attributeValue.getSid());
                        attributeValueVO.setLowerLimit(attributeValue
                                .getLowerLimit());
                        attributeValueVO.setUpperLimit(attributeValue
                                .getUpperLimit());
                        attributeValueVO.setRangeType(attributeValue
                                .getRangeType());
                        break;
                    }
                }
            }
        }// 如果不符合判定条件则没有获取到值对象，保留默认值无操作
        return attributeValueVOPage;
    }

    private String getTableNameOfObject(String object) {
        // 获取符合条件的对象集合
        Map<String, String> referenceMap = referenceService
                .findRefValueMap(ReferenceConstant.REFERENCE_ATTRIBUTE_VALUE_MAP);
        // 获取所有对象对应的属性表名称
        return referenceMap.get(object);
    }

    private Page<AttributeValueVO> findAttributesByPage(String object,
            String facilityId, Locale locale, Map<String, Object> attParams,
            int pageNo, int limit) {
        if (locale == null) {
            locale = new Locale("zh", "CN");
        }
        if (facilityId == null) {
            facilityId = LoginUtil.getFacilityIds();
        }
        
        logger.debug("locale=" + locale);
        Map<String, Object> params = new HashMap<String, Object>();
        // 根据传入参数不同处理查询参数条件
        params.put("object", object);
        params.put("facilityId", facilityId);
        if (attParams != null) {
            params.putAll(attParams);
        }
        // List<Attribute> totalAtrributes = attributeDao.findByParams(params);
        Page<Attribute> totalAtrributesByPage = attributeDao.findByPage(params,
                pageNo, limit);
        // 返回结果List对象
        List<AttributeValueVO> resultList = new ArrayList<AttributeValueVO>();
        // 遍历查询结果，完成转型
        for (Attribute attribute : totalAtrributesByPage.getResultList()) {
            // 创建新对象
            AttributeValueVO attributeValueVO = new AttributeValueVO();
            // 为对象的各个属性赋值 instanceSid 属性初始创建不赋值
            // logger.debug("attribute=" + attribute);
            attributeValueVO.setObject(attribute.getObject());
            attributeValueVO.setAttributeValue(attribute.getDefaultValue());
            attributeValueVO.setAttrDesc(attribute.getAttributeDesc());
            attributeValueVO.setFieldSid(attribute.getFieldSid());
            if (attribute.getFieldSid() != null) {
                FieldVO fieldVO = referenceService.findFieldContent(attribute
                        .getFieldSid(), locale);
                if(null!=fieldVO){
                attributeValueVO.setLabel(fieldVO.getFieldId());
                attributeValueVO.setFieldId(fieldVO.getFieldId());
                attributeValueVO.setFieldVO(fieldVO);
                }
            }
            // attributeValueVO.setLabel(attribute.getAttributeDesc());
            resultList.add(attributeValueVO);
        }
        Page<AttributeValueVO> attributeValueVOByPage = new Page<AttributeValueVO>();

        attributeValueVOByPage.setTotalRows(totalAtrributesByPage
                .getTotalRows());
        attributeValueVOByPage.setPageNo(pageNo);
        attributeValueVOByPage.setLimit(limit);
        attributeValueVOByPage.setResultList(resultList);
        return attributeValueVOByPage;
    }

    /* (non-Javadoc)
     * @see com.hp.core.service.AttributeValueService#findRealAttributeValues(java.lang.String, java.lang.String, java.lang.Long, java.util.Locale, java.util.Map, int, int)
     */
    public Page<AttributeValueVO> findRealAttributeValues(String object,
            String facilityId, Long instanceSid, Locale locale,
            Map<String, Object> attParams, int pageNo, int limit) {
        if (locale == null) {
            locale = new Locale("zh", "CN");
        }
        Map<String, Object> params = new HashMap<String, Object>();
        // 组装查询参数
        if (instanceSid != null) {
            params.put("instanceSid", instanceSid);
        }
        params.put("object", object);
        // 设置查询的表名已取到可直接使用
        String tableName = this.getTableNameOfObject(object);
        logger.debug("findAttributeValues tableName=" + tableName);
        params.put("tableName", tableName);
        if (attParams != null) {
            params.putAll(attParams);
        }
        Page<AttributeValueVO> attributeValuePage = attributeValueDao
                .findAttributeValueVOByPage(params, pageNo, limit);
        List<AttributeValueVO> attributeValueList = attributeValuePage
                .getResultList();
        List<AttributeValueVO> attrDefiniations = findAttributeValues(object,
                facilityId, locale, attParams);
        List<AttributeValueVO> resultList = new ArrayList<AttributeValueVO>();
        for (AttributeValueVO attribute : attributeValueList) {
            // 创建新对象
            AttributeValueVO attributeValueVO = new AttributeValueVO();
            for (AttributeValueVO avVo : attrDefiniations) {
                if (attribute.getObject().equals(avVo.getObject())
                        && attribute.getFieldSid().equals(avVo.getFieldSid())) {
                    attributeValueVO.setObject(attribute.getObject());
                    attributeValueVO.setFieldSid(attribute.getFieldSid());
                    attributeValueVO.setAttributeValue(attribute
                            .getAttributeValue());
                    if (attribute.getFieldSid() != null) {
                        FieldVO fieldVO = referenceService.findFieldContent(
                                attribute.getFieldSid(), locale);
                        attributeValueVO.setLabel(fieldVO.getContentText());
                        attributeValueVO.setFieldId(fieldVO.getFieldId());
                        attributeValueVO.setFieldVO(fieldVO);
                    }
                    attributeValueVO.setInstanceSid(attribute.getInstanceSid());
                    attributeValueVO.setLowerLimit(attribute.getLowerLimit());
                    attributeValueVO.setUpperLimit(attribute.getUpperLimit());
                    attributeValueVO.setRangeType(attribute.getRangeType());
                    attributeValueVO.setAttrDesc(avVo.getAttrDesc());
                    resultList.add(attributeValueVO);
                    break;
                }
            }
        }
        Page<AttributeValueVO> attributeValueVOByPage = new Page<AttributeValueVO>();

        attributeValueVOByPage.setTotalRows(attributeValuePage.getTotalRows());
        attributeValueVOByPage.setPageNo(pageNo);
        attributeValueVOByPage.setLimit(limit);
        attributeValueVOByPage.setResultList(resultList);
        return attributeValueVOByPage;
    }

    /* (non-Javadoc)
     * @see com.hp.core.service.AttributeValueService#findRealAttributeValues(java.lang.String, java.lang.String, java.lang.Long, java.util.Locale, java.util.Map)
     */
    public List<AttributeValueVO> findRealAttributeValues(String object,
            String facilityId, Long instanceSid, Locale locale,
            Map<String, Object> attParams) {
        Page<AttributeValueVO> p = this.findRealAttributeValues(object,
                facilityId, instanceSid, locale, attParams, 1,
                Integer.MAX_VALUE);
        return p.getResultList();
    }
}
